summaryrefslogtreecommitdiff
path: root/src/image.cpp
blob: 384de9a737d3f805a7c4366edf692891e2affe3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "image.h"
#include "palette.h"
#include "font.h"

#include <stdlib.h>
#include <string.h>
#include <png.h>

Image::Image() :
    iWidth( 0 ),
    iHeight( 0 ),
    pPix( NULL )
{
}

Image::Image( int32_t iWidth, int32_t iHeight ) :
    iWidth( iWidth ),
    iHeight( iHeight ),
    pPix( NULL )
{
    pPix = new uint8_t[iWidth*iHeight];
    clear();
}

Image::~Image()
{
    delete[] pPix;
}

void Image::clear( uint8_t uColor )
{
    memset( pPix, uColor, iWidth*iHeight );
}

void Image::set( int32_t x, int32_t y, uint8_t iCol )
{
    if( x < 0 || y < 0 || x >= iWidth || y >= iHeight )
        return;

    pPix[x+y*iWidth] = iCol;
}

void Image::save( const char *sPath, class Palette &rPal )
{
    uint8_t **pRows = new uint8_t*[iHeight];
    for( int r = 0; r < iHeight; r++ )
    {
        pRows[r] = pPix+(iWidth*r);
    }

    png_structp png_ptr = png_create_write_struct(
        PNG_LIBPNG_VER_STRING, NULL, NULL, NULL
        );
    png_infop info_ptr = png_create_info_struct(png_ptr);
    png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight,
        8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
        PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
        );
    png_color *pCol = new png_color[rPal.getCount()];
    for( int j = 0; j < rPal.getCount(); j++ )
    {
        uint8_t r, g, b;
        rPal.getColor( j, r, g, b );
        pCol[j].red = r;
        pCol[j].green = g;
        pCol[j].blue = b;
    }
    png_set_PLTE( png_ptr, info_ptr, pCol, rPal.getCount());

    png_set_rows( png_ptr, info_ptr, pRows );

    FILE *fp = fopen(sPath, "wb");
    if( fp == NULL )
    {
        printf("Error opening file!\n");
        exit( 1 );
    }
    
    png_init_io( png_ptr, fp );
    png_write_png( png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL );
    png_destroy_write_struct( &png_ptr, &info_ptr );
    fclose( fp );

    delete[] pCol;
    delete[] pRows;
}

void Image::drawText( class Font &rFnt, int32_t x, int32_t y, uint8_t uColor,
        const char *sText )
{
    for( const char *s = sText; *s; s++ )
    {
        Font::Glyph *pGlyph = rFnt.get( *s );
        if( pGlyph == NULL )
            continue;

        for( int cy = 0; cy < pGlyph->pBox.y; cy++ )
        {
            for( int cx = 0; cx < pGlyph->pBox.x; cx++ )
            {
                int bit = 1<<(7-(cx%8));
                int byte = cx/8;
                if( pGlyph->pData[byte+cy*pGlyph->iRowBytes]&bit )
                    set( x+cx, y+cy-pGlyph->pBox.y-pGlyph->pOff.y, uColor );
            }
        }
        x += pGlyph->pDevOff.x;
        y += pGlyph->pDevOff.y;
    }
}

void Image::drawLine( int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t uColor )
{
    if( x1 == x2 )
    {
        // Vertical line, easy
        if( y2 < y1 )
        {
            int32_t r = y2;
            y2 = y1;
            y1 = r;
        }
        for( int j = y1; j <= y2; j++ )
        {
            set( x1, j, uColor );
        }
    }
    else if( y1 == y2 )
    {
        // Horizontal line, easy
        if( x2 < x1 )
        {
            int32_t r = x2;
            x2 = x1;
            x1 = r;
        }
        for( int j = x1; j <= x2; j++ )
        {
            set( j, y1, uColor );
        }
    }
}